#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/un.h>
#include <unistd.h>

#include "r_socket_common.h"

#include "r_socket_domain_udp_partner.h"
#include "r_socket_obj_manager.h"

#include "utilities/string_operator.h"
#include "utilities/r_logger.h"

namespace eniac
{

r_socket_proxy_ret_t r_socket_domain_udp_partner::send_message(const r_socket::ptr socket_obj, const std::vector<uint8_t>& message)
{
    if (nullptr == socket_obj.get())
    {
        return r_socket_proxy_ret_t::NULL_PTR;
    }

    if (0 == message.size())
    {
        return r_socket_proxy_ret_t::NO_DATA_CAN_BE_SENT;
    }

    r_socket::ptr host_socket = r_socket_obj_manager::get_instance()->get_socket_obj_by_id(socket_obj->m_host_id);
    if (nullptr == host_socket.get())
    {
        return r_socket_proxy_ret_t::HOST_SOCKET_OBJ_IS_NOT_FOUND;
    }

    if (INVALID_SOCKET_FD == host_socket->m_socket_fd)
    {
        return r_socket_proxy_ret_t::HOST_SOCKET_FD_IS_INVALID;
    }

    std::lock_guard<std::mutex> lg{host_socket->m_mutex};

    struct sockaddr_un partner_addr;
    memset(&partner_addr, 0, sizeof(partner_addr));
    partner_addr.sun_family = AF_UNIX;
    strncpy(&partner_addr.sun_path[1], socket_obj->m_own_address.data(), sizeof(partner_addr.sun_path) - 2);

    LOG_DBG() << "Partner Address is " << socket_obj->m_own_address;

    ssize_t send_len = sendto(
        host_socket->m_socket_fd,
        message.data(),
        message.size(),
        0,
        (struct sockaddr*)&partner_addr,
        sizeof(partner_addr)
    );
    if (send_len != message.size())
    {
        //TODO Make Sure ALL Data is sent
        return r_socket_proxy_ret_t::TO_SEND_DATA_IS_FAILED;
    }

    LOG_DBG() << "To send Message is success";
    return r_socket_proxy_ret_t::OK;
}



}